/**
 * This class tests the Marketplace class.
 * @author Michelle Partogi
 * @version 1.0
 */

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertEquals;


import java.util.Arrays;

import org.junit.Before;
import org.junit.Test;



/**
 * @author Michelle Partogi
 * @version 1.0
 */
public class MarketplaceTest {
	/**
	 * Field player.
	 */
	private Player player;

	/**
	 * Field gui.
	 */
	private SpaceTraderGui gui;

	/**
	 * Field system.
	 */
	private SolarSystem system;

	/**
	 * Field testMP.
	 */
	private Marketplace testMP;
	
	/**
	 * Testing skillpoints
	 */
	private static final int SKILL = 4;
	
	/**
	 * Starting credits
	 */
	private static final int INIT_CRED = 1000;
	
	/**
	 * Testing credits
	 */
	private static final int TEST_CRED = 10050;
	
	/**
	 * Number of goods to purchase
	 */
	private static final int TEST_BUY = 60;
	
	/**
	 * Number of goods to sell
	 */
	private static final int TEST_SELL = 60;
	
	/**
	 * Goods checker
	 */
	private static final int GOODS_CHECK = 59;
	
	/**
	 * Events num
	 */
	private static final int EVENTS_NUM = 50;
	
	/**
	 * Method start.
	 */
	@Before
	public void start(){
		gui = new SpaceTraderGui();
		player = new Player("Test", SKILL, SKILL, SKILL, SKILL, INIT_CRED); //start with 1000 credits
		gui.startGame(player);
		system = new SolarSystem("PlanetTest");
		system.setResource("No Special Resources");
		testMP = new Marketplace(player, system, gui) ;
	}
	
	/**
	 * toString method.
	
	 * @return String */
	public String toString() {
		return "";
	}

		/**
		 * Method testSetCredits.
		 */
	@Test
	public void testSetCredits() {
		player.setCredits(TEST_CRED);
		assertEquals("assertion failed", player.getCredits(), TEST_CRED);
	}

		/**
		 * Method testSetMarketplace.
		 */
		@Test
		public void testSetMarketplace() {
		final Marketplace testMP = new Marketplace(player, system, gui) ;
		gui.setMarketplace(testMP);
		assertTrue("assertion failed", gui.getMarketplace().equals(testMP));
	}

	/*
	 * Test if buying stops correctly when manually clicking.
	 * Tries to buy all the water in one solar system and then some.
	 * Should max out due to cargo limit or lack of funds.
	 * Also checks that gui credits are updated properly
	 */
	/**
	 * Method testManualMaxBuy.
	 */
	@Test
	public void testManualMaxBuy() {
		final int[] goods = {TEST_BUY, 0, 0, 0, 0, 0, 0, 0, 0, 0};
		system.setGoods(goods); 
		final int count = player.getCredits() / testMP.getBuyPrices()[0];
		for (int i=0; i <= system.getGoods()[0] + 1;i++){
			testMP.getBtnBuyOne()[0].doClick();
		}
		assertTrue("assertion failed", gui.getLblCredits().getText().equals
				("Credits: " + player.getCredits()) &&
				player.getShip().getGoods()[0] == 
				(count * testMP.getBuyPrices()[0] + INIT_CRED) && 
				player.getShip().getGoods()[0] == count && 
				player.getCredits() <= testMP.getBuyPrices()[0] && 
				player.getCredits() >= 0 || 
				player.getShip().getCargo() <= player.getShip().getMaxCargo() );
	}
	
	/*
	 * Test if buying stops correctly when using "Buy All" button clicking.
	 * Tries to buy all the water in one solar system and then some.
	 * Should max out due to cargo limit or lack of funds.
	 * Credits should equal max number of water player can buy
	 */
	/**
	 * Method testMaxBuy.
	 */
	@Test
	public void testMaxBuy() {
		final int[] goods = {TEST_BUY, 0, 0, 0, 0, 0, 0, 0, 0, 0};
		system.setGoods(goods); 
		final int count = player.getCredits() / testMP.getBuyPrices()[0];
		testMP.getBtnBuyAll()[0].doClick();
		assertTrue("assertion failed", gui.getLblCredits().getText().equals
				("Credits: " + player.getCredits()) &&
				player.getShip().getGoods()[0] == 
				(count * testMP.getBuyPrices()[0] + INIT_CRED) && 
				player.getShip().getGoods()[0] == count && 
				player.getCredits() <= testMP.getBuyPrices()[0] && 
				player.getCredits() >= 0 || 
				player.getShip().getCargo() <= player.getShip().getMaxCargo() );
	}

	/*
	 * Has player start with 60 waters
	 * Player will sell goods one by one 61 times.
	 * Correct player credits should be generated
	 * and player should have 0 waters in cargo
	 */
	/**
	 * Method testManualMaxSell.
	 */
	@Test
	public void testManualMaxSell() {
		final int[] goods = {TEST_SELL, 0, 0, 0, 0, 0, 0, 0, 0, 0};
		player.getShip().setGoods(goods);
		for (int i=0; i <= system.getGoods()[0] + 1;i++){
			testMP.getBtnSellOne()[0].doClick();
		}
		assertTrue("assertion failed", gui.getLblCredits().getText().equals
				("Credits: " + player.getCredits()) &&
				player.getCredits() == testMP.getSellPrices()[0] * TEST_SELL
				+ INIT_CRED && player.getShip().getGoods()[0] == 0);
	}
	
	/*
	 * Has player start with 60 waters
	 * Player will sell all of it and get correct amount
	 */
	/**
	 * Method testMaxSell.
	 */
	@Test
	public void testMaxSell() {
		final int[] goods = {TEST_SELL, 0, 0, 0, 0, 0, 0, 0, 0, 0};
		player.getShip().setGoods(goods);
		testMP.getBtnSellAll()[0].doClick();
		assertTrue("assertion failed", gui.getLblCredits().getText()
				.equals("Credits: " + player.getCredits()) &&
				player.getCredits() == testMP.getSellPrices()[0] * TEST_SELL
				+ INIT_CRED && player.getShip().getGoods()[0] == 0);
	}
	
	/*
	 * Test sell one and update credit correctly as well as cargo decrease
	 */
	/**
	 * Method testSellOne.
	 */
	@Test
	public void testSellOne() {
		final int[] goods = {TEST_SELL, 0, 0, 0, 0, 0, 0, 0, 0, 0};
		player.getShip().setGoods(goods);
		testMP.getBtnSellOne()[0].doClick();
		assertTrue("assertion failed", gui.getLblCredits().getText()
				.equals("Credits: " + player.getCredits()) &&
				player.getCredits() == testMP.getSellPrices()[0] + INIT_CRED
				&& player.getShip().getGoods()[0] == GOODS_CHECK);
	}

	/*
	 * Test drought event to see if in 50 random creations of marketplace
	 * the one in drought will always have a higher buy/sell price for water
	 */
	/**
	 * Method testEvent.
	 */
	@Test
	public void testEvent(){
		boolean answer = true;
		for (int i = 0; i < EVENTS_NUM; i++){
			if (canEventCreate()){
				answer = false;
			}
		}
		assertTrue("assertion failed", answer);
	}
	
	/**
	 * Method eventCreate generates a new marketplace with a drought.
	 * This should make water more valuable
	
	 * @return boolean */
	public boolean canEventCreate(){
		final Marketplace newMP = new Marketplace(player, system, gui, "Drought");
		final Marketplace anotherMP = new Marketplace(player, system, gui, "None");
		return ( anotherMP.getBuyPrices()[0] >=  newMP.getBuyPrices()[0] && 
				anotherMP.getSellPrices()[0] <=  newMP.getSellPrices()[0] );
	}

	/**
	 * Method testNewMarketPlace.
	 */
	@Test
	public void testNewMarketPlace() {
		final SolarSystem newSyst = new SolarSystem("Test 2");
		gui.setCurrentSystem(system); 
		final int[] oldSP = gui.getMarketplace().getSellPrices(); 
		final int[] oldBP = gui.getMarketplace().getBuyPrices(); 
		gui.setTargetSystem(newSyst);
		gui.getBtnWarp().setEnabled(true);
		gui.getBtnWarp().doClick();
		final int[] newSP = gui.getMarketplace().getSellPrices(); 
		final int[] newBP = gui.getMarketplace().getBuyPrices(); 
		assertFalse ("assertion failed", Arrays.equals(newBP, oldBP) 
				&&  Arrays.equals(newSP, oldSP));
	}

}
